package org.apache.struts.ehr.medical_records.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.mail.Address;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts.ehr.medical_records.model.AdmitPatient;
import org.apache.struts.ehr.medical_records.model.Bht;
import org.apache.struts.ehr.medical_records.model.Guardian;
import org.apache.struts.ehr.medical_records.model.GuardianForPatientDetails;
import org.apache.struts.ehr.medical_records.model.HL7Message;
import org.apache.struts.ehr.medical_records.model.MedicalRecords;
import org.apache.struts.ehr.medical_records.model.PatientRecords;
import org.apache.struts.ehr.medical_records.model.Query;
import org.apache.struts.ehr.medical_records.model.ReplyMessage;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts.ehr.patient_details.model.Patient;
import org.apache.struts.ehr.patient_details.model.PatientDetails;
import org.apache.struts.pharmacy.pharmacy.action.SearchResultsAction;
import org.apache.struts.pharmacy.pharmacy.model.DrugsGivenToPatient;
import org.apache.struts.pharmacy.pharmacy.model.PrescriptionDrugs;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.DataTypeException;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.v251.datatype.XAD;
import ca.uhn.hl7v2.model.v251.datatype.XTN;
import ca.uhn.hl7v2.model.v251.message.ADR_A19;
import ca.uhn.hl7v2.model.v251.message.TBR_R08;
import ca.uhn.hl7v2.model.v251.segment.DG1;
import ca.uhn.hl7v2.model.v251.segment.NK1;
import ca.uhn.hl7v2.model.v251.segment.OBX;
import ca.uhn.hl7v2.model.v251.segment.PID;
import ca.uhn.hl7v2.model.v251.segment.PV1;
import ca.uhn.hl7v2.model.v251.segment.PV2;
import ca.uhn.hl7v2.parser.EncodingNotSupportedException;
import ca.uhn.hl7v2.parser.PipeParser;

import com.earogya.Constants;
import com.earogya.communicate.Communicator;
import com.earogya.logic.medical_records.CreateQRYA19;
import com.earogya.logic.medical_records.ParseReply;
import com.earogya.logic.pharmacy.request.CreateEQQQ04;
import com.earogya.logic.pharmacy.request.TBR_R08_Handler;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

/***
 * This class is the struts action to view patient detials of the
 * current admission.
 * @author Chamendri
 *
 */
public class ViewPatientDetailsAction extends ActionSupport  implements ServletRequestAware {

	private HttpServletRequest request;
	private PatientRecords records;
	private ReplyMessage replyMessage;
	private HL7Message message=new HL7Message();
	private Patient details;
	private List <DrugsGivenToPatient> prescriptionDrugsList;

	
	public HL7Message getMessage() {
		return message;
	}

	public List<DrugsGivenToPatient> getPrescriptionDrugsList() {
		return prescriptionDrugsList;
	}

	public Patient getDetails() {
		return details;
	}

	public ReplyMessage getReplyMessage() {
		return replyMessage;
	}

	public PatientRecords getRecords() {
		return records;
	}

	/**
	 * Overrides execute method of ActionSupport interface.
	 * Creates QRY A19 method with the search type "admission".
	 * The patient id parameter of the Query object should be set
	 * as "ward_no,bed_no".
	 */
	public String execute()throws Exception{
		Map<String, Object> session=ActionContext.getContext().getSession();
		replyMessage=new ReplyMessage();
		replyMessage.setMessage(Constants.EMPTY);
		Query query=new Query();
		query.setPatientId(request.getParameter("ward_no")+","+request.getParameter("bed_no"));
		query.setSearch_type(Constants.ADMISSION);
		CreateQRYA19 createMessage=new CreateQRYA19(query);
		String msg=createMessage.createMessage(Constants.SENDING_FACILITY);
		if(!msg.equals(null)){
			Communicator c=new Communicator();
			String reply=c.sendMessage(msg);
			if(!reply.equals(Constants.NO_REPLY)){
				ParseReply parse=new ParseReply();
				try{
					ADR_A19 adr=(ADR_A19)parse.parseMessage(reply);
					this.setValuesToAdmission(adr);
				}catch(ClassCastException e){
					replyMessage=(ReplyMessage)parse.parseMessage(reply);
				}
			}
		}
		PatientDetails patient_detials=new PatientDetails();
		patient_detials.getPatient().setPatientId(records.getPatient_id());
		com.earogya.logic.patient_details.CreateQRYA19 qry=new com.earogya.logic.patient_details.CreateQRYA19(patient_detials);
		String msg_patient_details=qry.createMessage(Constants.SENDING_FACILITY);
		if(!msg_patient_details.equals(null)){
			Communicator c=new Communicator();
			String reply=c.sendMessage(msg_patient_details);
			if(!reply.equals(Constants.NO_REPLY)){
				ParseReply parse=new ParseReply();
				try{
					ADR_A19 adr=(ADR_A19)parse.parseMessage(reply);
					this.setValuestoPatientDetails(adr);
				}catch(ClassCastException e){
					replyMessage=(ReplyMessage)parse.parseMessage(reply);
				}
			}
		}
		
		//by kapila
		PrescriptionDrugs prescriptionDrugs=new PrescriptionDrugs();
		prescriptionDrugs.setPatientId(records.getPatient_id());
		CreateEQQQ04 createMessageDrugs = new CreateEQQQ04(prescriptionDrugs);
		String msgDrugs = createMessageDrugs.createMessage((String) session
				.get("facility"));
		if (!msgDrugs.equals(null)) {
			Communicator c = new Communicator();
			String reply = c.sendMessage(msgDrugs);
			if(!reply.equals(Constants.NO_REPLY)){
				if (!reply.contains("RDT|no results found")){//.equals("No Reply")) {
					TBR_R08_Handler handler=new TBR_R08_Handler(createTBR_R08Msg(reply));
					prescriptionDrugsList=handler.manageMessage();
				} else {
					message.setMessage("No Results Found");
				}
			} else {
				message.setMessage(Constants.NO_REPLY);
			}
			message.setMessage(Constants.EMPTY);
		}else{
			message.setMessage("failed to create message");
			return ERROR;
		}
		return SUCCESS;
	}

	public void setServletRequest(HttpServletRequest arg0) {
		this.request = arg0;	
	}
	
	/**
	 * Parser an ADR A19 message and add values to PatientRecords class.
	 * @param adr An ADR A19 object
	 * @throws HL7Exception
	 */
	private void setValuesToAdmission(ADR_A19 adr) throws HL7Exception{
		this.records=new PatientRecords();
		PID pid=adr.getQUERY_RESPONSE().getPID();
		records.setPatient_id(pid.getPatientID().getIDNumber().getValue());
		
		PV1 pv1=adr.getQUERY_RESPONSE().getPV1();
		records.setAdmission_date(pv1.getAdmitDateTime().getTime().getValueAsDate());
		records.setAdmiting_officer(pv1.getAdmittingDoctor(0).getIDNumber().getValue());
		records.setBed(pv1.getPriorPatientLocation().getBed().getValue());
		records.setWard(pv1.getPriorPatientLocation().getRoom().getValue());
		records.setNo_of_Admssions(Integer.parseInt(pv1.getVisitIndicator().getValue()));
		Bht bht=new Bht();
		bht.setCurrent_bed(pv1.getAssignedPatientLocation().getBed().getValue());
		bht.setCurrent_ward(pv1.getAssignedPatientLocation().getRoom().getValue());
		bht.setConsultant_id(pv1.getConsultingDoctor(0).getIDNumber().getValue());
		records.setBht(bht);
		
		PV2 pv2=adr.getQUERY_RESPONSE().getPV2();
		records.setAdmit_reason(pv2.getAdmitReason().getText().getValue());
		
		int numberOfObservations=adr.getQUERY_RESPONSE().getOBXReps();
		int numberOfDiagonosis=adr.getQUERY_RESPONSE().getDG1Reps();
		int maxLength=numberOfDiagonosis;
		if(numberOfObservations>numberOfDiagonosis){
			maxLength=numberOfObservations;
		}
		ArrayList<MedicalRecords> medicalRecordsList=new ArrayList<MedicalRecords>();
		for(int i=0; i<maxLength; i++){
			MedicalRecords medicalRecords=new MedicalRecords();
			if(i<numberOfObservations){
				OBX obx=adr.getQUERY_RESPONSE().getOBX(i);
				medicalRecords.setObservation(obx.getObservationValue(0).getData().encode());
				medicalRecords.setObserverId(obx.getResponsibleObserver(0).getIDNumber().getValue());
				medicalRecords.setObservationdate(obx.getDateTimeOfTheObservation().getTime().getValueAsDate());
			}
			else{
				medicalRecords.setObservation("");
				medicalRecords.setObserverId("");
			}
			if(i<numberOfDiagonosis){
				DG1 dg1=adr.getQUERY_RESPONSE().getDG1(i);
				medicalRecords.setDiagosis(dg1.getDiagnosisDescription().getValue());
				medicalRecords.setDiagnosingClinicianId(dg1.getDiagnosingClinician(0).getIDNumber().getValue());
				medicalRecords.setDiagnosingDate(dg1.getDiagnosisDateTime().getTime().getValueAsDate());
			}
			else{
				medicalRecords.setDiagosis("");
				medicalRecords.setDiagnosingClinicianId("");
			}
			medicalRecordsList.add(medicalRecords);
		}
		records.setMedicalRecords(medicalRecordsList);
		
		GuardianForPatientDetails guardian=new GuardianForPatientDetails();
		NK1 nk1=adr.getQUERY_RESPONSE().getNK1();
		guardian.setPrefix(nk1.getNK1Name(0).getPrefixEgDR().getValue());
		guardian.setGiven_name(nk1.getNK1Name(0).getGivenName().getValue());
		guardian.setFurthur_names(nk1.getNK1Name(0).getSecondAndFurtherGivenNamesOrInitialsThereof().getValue());
		guardian.setSurname(nk1.getNK1Name(0).getFamilyName().getSurname().getValue());
		guardian.setNic_no(nk1.getContactPersonSocialSecurityNumber().getValue());
		guardian.setGuardian_relationship(nk1.getRelationship().getText().getValue());
		
		ArrayList<org.apache.struts.ehr.medical_records.model.Address> addressList=new ArrayList<org.apache.struts.ehr.medical_records.model.Address>();
		XAD[] addresses=nk1.getAddress();
		for(int i=0; i<addresses.length; i++){
			org.apache.struts.ehr.medical_records.model.Address address=new org.apache.struts.ehr.medical_records.model.Address();
			address.setHouse_number(addresses[i].getStreetAddress().getDwellingNumber().getValue());
			address.setStreet(addresses[i].getStreetAddress().getStreetName().getValue());
			address.setCity_1(addresses[i].getOtherDesignation().getValue());
			address.setCity_2(addresses[i].getCity().getValue());
			address.setCountry(addresses[i].getCountry().getValue());
			addressList.add(address);
		}
		guardian.setAddresses(addressList);
		
		ArrayList<String> telephoneNumberList=new ArrayList<String>();
		ArrayList<String> emailList=new ArrayList<String>();
		XTN[] telephoneNumbers=nk1.getPhoneNumber();
		for(int i=0; i<telephoneNumbers.length; i++){
			telephoneNumberList.add(telephoneNumbers[i].getTelephoneNumber().getValue());
			if(telephoneNumbers[i].getEmailAddress()!=null){
				emailList.add(telephoneNumbers[i].getEmailAddress().getValue());
			}
		}
		guardian.setTelephoneNumbers(telephoneNumberList);
		guardian.setEmail(emailList);
		records.setGuardian(guardian);
	}
	
	/***
	 * Set values to patient detials object. By Ureka
	 * @param adr
	 * @throws DataTypeException
	 */
	private void setValuestoPatientDetails(ADR_A19 adr) throws DataTypeException{
		this.details=new Patient();
		PID pid=adr.getQUERY_RESPONSE().getPID();
		if(pid.getDateTimeOfBirth().getTime().getValue()==null){}
		else{
			details.setBirthTime(pid.getDateTimeOfBirth().getTime().getValueAsDate());
		}
		details.setGender(pid.getAdministrativeSex().getValue());
		String prefix=pid.getPatientName(0).getPrefixEgDR().getValue();
		String givenName=pid.getPatientName(0).getGivenName().getValue();
		String familyName=pid.getPatientName(0).getFamilyName().getSurname().getValue();
		if(prefix==null || prefix.equals("null")){
			prefix="";
		}
		if(givenName==null || givenName.equals("null")){
			givenName="";
		}
		if(familyName==null || familyName.equals("null")){
			familyName="";
		}
		details.setGivenName(prefix+" "+givenName+" "+familyName);
		
	}
	
	/***
	 * Create TBR message. By Kapila
	 * @param message
	 * @return
	 * @throws EncodingNotSupportedException
	 * @throws HL7Exception
	 */
	public TBR_R08 createTBR_R08Msg(String message) throws EncodingNotSupportedException, HL7Exception{
		Message hapiMsg  = new PipeParser().parse(message);
		return (TBR_R08)hapiMsg;
	}
}
